<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/12/1
 * Time: 19:35
 */

namespace app\api\service;


use app\api\model\Book;
use app\api\model\Order as OrderModel;
use app\api\model\OrderBook;
use app\api\model\UserAddress;
use app\api\service\Token as TokenService;
use app\lib\enum\OrderTypeEnum;
use app\lib\enum\ScopeEnum;
use app\lib\Exception\ForbiddenException;
use app\lib\Exception\OrderException;
use app\lib\Exception\UserException;
use think\Db;
use think\Exception;

class Order
{

    protected $uid;
    protected $oBooks;
    protected $books;
    protected $type;

    public function place($oBooks, $orderType, $uid)
    {
        $this->oBooks = $oBooks;
        $this->type = $orderType;
        $this->uid = $uid;
        $this->books = $this->getBooksByOrder($oBooks);


        // 获取订单状态
        $orderState = $this->getOrderStatus();
        if(!$orderState['pass']){
            $orderState['order_id'] = -1;
            return $orderState;
            // throw new OrderException([
            //     'info'=>'库存不足，创建订单失败'
            // ]);
         }



        // 生成订单快照
        $snap = $this->SnapOrder($orderState);

        // createOrder
        $order = $this->createOrder($snap);
        $order['pass'] = true;
        return $order;
    }

    public static function checkOrderValid($orderID,$orderType,$orderStatus){
        $order = OrderModel::get($orderID);
        if(!$order){
            throw new OrderException();
        }

        // 权限
        if(TokenService::getTokenVar("scope") < ScopeEnum::Super){
            if(!TokenService::isValidateOperate($order->user_id)){
                throw new UserException([
                    'info'=>'订单与用户不匹配',
                    'errorCode'=> 80002
                ]);
            }
        }


        if($order->order_type != $orderType){
            throw new OrderException([
                'info'=> '订单类型错误',
                'errorCode' => 80004,
                'stateCode'=>400
            ]);
        }


        if($order->status != $orderStatus){
            throw new OrderException([
                'info'=> '订单状态错误',
                'errorCode'=> 80006,
                'stateCode'=>400
            ]);
        }
        return true;
    }

    private function createOrder($snap){
        Db::startTrans();
        try{
        $orderNo = self::makeOrderNo();
        $order = new OrderModel();
        $order->order_no = $orderNo;
        $order->user_id = $this->uid;
        $order->order_type = $this->type;
        $order->snap_name = $snap['snapName'];
        $order->snap_img = $snap['snapImg'];
        $order->total_price = $snap['orderPrice'];
        $order->total_count = $snap['totalCount'];
        $order->snap_address = $snap['snapAddress'];
        $order->snap_items = json_encode($snap['bookStatus']);

        $order->save();
        $orderID = $order->id;

        $createTime = $order->create_time;
    //    orderProduct  更新

        foreach ($this->oBooks as &$book){
            $book['order_id'] = $orderID;
        }

        $orderBook = new OrderBook();
        $orderBook->saveAll($this->oBooks);

        Db::commit();
        return [
            'order_no'=>$orderNo,
            'order_id'=>$orderID,
            'create_time'=>$createTime
        ];
        }
        catch (Exception $ex){
            Db::rollback();
            throw $ex;
        }
    }

    private function SnapOrder($orderState){
        $snap = [
            'orderPrice' => 0,
            'totalCount' => 0,
            'bookStatus' => [],
            'snapAddress' => json_encode($this->getUserAddress()),
            'snapName' => $this->books[0]['name'],
            'snapImg'=>$this->books[0]['main_img_url'],

        ];

        $snap['orderPrice'] = $orderState['orderPrice'];
        $snap['totalCount'] = $orderState['totalCount'];
        $snap['bookStatus'] = $orderState['bookStatusArray'];

        if(count($this->oBooks) > 1){
            $snap['snapName'] .= '等';
        }

        return $snap;
    }


    private function getUserAddress(){
        $userAddress = UserAddress::where('user_id','=',$this->uid)->find();
        if(!$userAddress){
            throw new UserException([
                'info'=> '用户地址不存在，下单失败'
            ]);
        }
        return $userAddress;
    }

    /*
     * @ 'sell'=>true 用户买书   false 用户卖书
     * */
    private function getOrderStatus()
    {
        $orderStatus =[
            'pass'=>true,
            'bookStatusArray'=>[],
            'orderPrice'=>0,
            'totalCount'=>0
        ];

        foreach ($this->oBooks as $oBook)
        {
            $bookStatus = $this->getBookStatue($oBook['book_id'], $oBook['count'], $this->books);

            $orderStatus['orderPrice'] += $bookStatus['totalPrice'];
            $orderStatus['totalCount'] += $bookStatus['count'];
            array_push($orderStatus['bookStatusArray'], $bookStatus);

            if(!$bookStatus['haveStock'])
            {
                $orderStatus['pass'] = false;
            }
        }
        return $orderStatus;
    }



    public function checkOrderState($orderId){
        $this->oBooks = OrderBook::where('order_id','=',$orderId)->select();
        $orderModel = OrderModel::get($orderId);
        $this->type = $orderModel->order_type;
        $this->books = $this->getBooksByOrder($this->oBooks);
        return $this->getOrderStatus();
    }

    private function getBooksByOrder($oBooks)
    {
        $bookIDArray = [];
        foreach ($oBooks as $oBook){
            array_push($bookIDArray,$oBook['book_id']);
        }

        return Book::all($bookIDArray)->visible(['id','name','price','stock','main_img_url','discount','rate','isbn'])->toArray();
    }

    private function getBookStatue($bID,$bCount,$books)
    {
        $bookStatus = [
            'id'=>'',
            'name'=>'',
            'stock'=>'',
            'isbn'=>'',
            'haveStock'=>false,
            'totalPrice'=>0,
            'count' => 0,
            'main_img_url'=>'',
            'price' => 0
        ];

        $bIndex = -1;
        for($i=0; $i<count($books); $i++){
            if($bID == $books[$i]['id'] ){
                $bIndex = $i;
            }
        }

        if($bIndex < 0){
            throw new OrderException([
                'info'=>'id为' . $bID . '的商品不存在，订单创建失败'
            ]);
        }

        $book = $books[$bIndex];
        $bookStatus['id'] = $book['id'];
        $bookStatus['name'] = $book['name'];
        $bookStatus['stock'] = $book['stock'];
        $bookStatus['isbn'] = $book['isbn'];
        $bookStatus['haveStock'] = $book['stock'] >= $bCount ? true : false;

        // 这两个属性是为了前端部分容易显示
        $bookStatus['main_img_url'] = $book['main_img_url'];
        // $bookStatus['price'] = $book['price'];

        // 前端先乘折扣 toFixed   再乘数量 toFixed
        // 折扣后的单价
        if($this->type == OrderTypeEnum::Buy){
            $bookStatus['price'] = round($book['price'] * $book['discount'], 1);
        } else{
            $bookStatus['price'] = round($book['price'] * $book['rate'], 1);
            // recycle 订单不用库存检测
            $bookStatus['haveStock'] = true;
        }

        $bookStatus['totalPrice'] = round($bookStatus['price'] * $bCount, 1);

        $bookStatus['count'] = $bCount;

        return $bookStatus;
    }


    public static function makeOrderNo()
    {
        $yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
        $orderSn = $yCode[intval(date('Y')) - 2017] . strtoupper(dechex(date('m'))) . date(
                'd') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf(
                '%02d', rand(0, 99));
        return $orderSn;
    }

    public static function isLegalOperate($checkedOrderID){
        // $scope = TokenService::getTokenVar('scope');
        // super权限可以查看
        // if($scope >= ScopeEnum::Super){
        //     return true;
        // } else{
            // 用户只能查看自己的订单
            $order = OrderModel::get($checkedOrderID);

            // 订单不存在
            if(!$order){
                throw new OrderException();
            }

            // 是这个用户的订单吗
            $legal = TokenService::isValidateOperate($order->user_id);
            if($legal){
                return true;
            }
            throw new ForbiddenException();
        }
    // }
}